/*
   This class can be inherited from to create forms as widgets that do not send form POST data - but rather, perform custom actions.
   It is up to the child of this class to emit the formExecuted notification - putting this in a DialogForm will not function correctly.
   
   Please remember to add any widgets you want validated to this.mChildWidgets.
*/
define(
   [
      'dojo/_base/declare',
	   'dojo/_base/array', // array.every array.filter array.forEach array.indexOf array.map
      'dojo/_base/lang',
      'noBusinessBase/widgets/ButtonRow',
      'noBusinessBase/form/WidgetBase',
      'dojo/window'
   ],
   function(declare, array, lang, ButtonRow, WidgetBase, winUtils)
   {
      return declare([WidgetBase],
      {
         mNoButtonRow: false,
         mCancelLabel: "Cancel",
         mCancelIconClass: "icons-fugue-icons-16x16-cross-script",
         mSubmitBusyLabel: "Submitting...",
         mSubmitIconClass: "icons-diagona-icons-16x16-102",
         mSubmitLabel: "Submit",
         mCancel: true,
         mEmitted: false,
         warnOnCancel: false,
         postCreate: function()
         {
            this.inherited(arguments);
            
            if(this.mNoButtonRow)
               return;
            
            this.mButtonRow = new ButtonRow({
               mCancelLabel:      this.mCancelLabel,
               mCancelIconClass: this.mCancelIconClass,
               mSubmitBusyLabel: this.mSubmitBusyLabel,
               mSubmitIconClass: this.mSubmitIconClass,
               mSubmitLabel:     this.mSubmitLabel,
               mApply:           this.mApply,
               mBack:            false,
               mNext:            false,
               mCancel:          this.mCancel
            }, this.mAttachPointForButtonRow);
            this.mChildWidgets.push(this.mButtonRow);

            this.own(
               this.mButtonRow.on('submit', lang.hitch(this, function()
               {
                  if(this.validate && !this.validate())
                  {
                     this.mButtonRow.reset();
                     return;
                  }
                  if(this.emitFormExecuted)
                  {
                     if(!this.mEmitted)
                        this.mEmitted = this.emitFormExecuted();

                     if(!this.mEmitted)
                        this.mButtonRow.reset();
                  }
                  else
                  {
                     console.error("Child class of noBusinessBase/form/WidgetFakeForm must implement emitFormExecuted.");
                     this.mButtonRow.reset();
                  }
               })),
               this.mButtonRow.on('cancel', lang.hitch(this, function()
               {
                  this.onCancelClicked();
               })),
               this.mButtonRow.on('apply', lang.hitch(this, function()
               {
                  if(this.emitFormExecuted)
                     this.emitFormExecuted(false);
                  else
                  {
                     console.error("Child class of noBusinessBase/form/WidgetFakeForm must implement emitFormExecuted.");
                     this.mButtonRow.reset();
                  }
               }))
            );

         },

      //Update from _formMixin on dojo updates
      //
      //
      //
		_getDescendantFormWidgets: function(/*dijit/_WidgetBase[]?*/ children){
			// summary:
			//		Returns all form widget descendants, searching through non-form child widgets like BorderContainer
			var res = [];
			array.forEach(children || this.getChildren(), function(child){
				if("value" in child){
					res.push(child);
				}else{
					res = res.concat(this._getDescendantFormWidgets(child.getChildren()));
				}
			}, this);
			return res;
		},

		reset: function(){
			array.forEach(this._getDescendantFormWidgets(), function(widget){
				if(widget.reset){
					widget.reset();
				}
			});
		},
      onCancelClicked: function()
      {
         if(this.emitFormCanceled)
            this.emitFormCanceled();
         this.emit('formCanceled');
      },
      formHasChanges: function(ev)
      {
         this.inherited(arguments);
         if(this.warnOnCancel && ev.hasChanges)
         {
            this.onCancelClicked = lang.hitch(this, function()
            {
               if(confirm("You have unsaved changes! Are you sure you want to close?"))
                  return this.inherited("onCancelClicked", arguments);

               return null;
            });
         }
         else
         {
            this.onCancelClicked = lang.hitch(this, function()
            {
               if(this.emitFormCanceled)
                  this.emitFormCanceled();
               this.emit('formCanceled');
            });
         }
      },
		validate: function(){
			// summary:
			//		returns if the form is valid - same as isValid - but
			//		provides a few additional (ui-specific) features:
			//
			//		1. it will highlight any sub-widgets that are not valid
			//		2. it will call focus() on the first invalid sub-widget
			var didFocus = false;
			return array.every(array.map(this._getDescendantFormWidgets(), function(widget){
				// Need to set this so that "required" widgets get their
				// state set.
				widget._hasBeenBlurred = true;
				var valid = widget.disabled || !widget.validate || widget.validate();
				if(!valid && !didFocus){
					// Set focus of the first non-valid widget
					winUtils.scrollIntoView(widget.containerNode || widget.domNode);
					widget.focus();
					didFocus = true;
				}
				return valid;
			}), function(item){ return item; });
		}
      
      });
   }
);
